package com.party.mobile.web.controller.member;

import com.google.common.base.Function;
import com.party.authorization.annotation.Authorization;
import com.party.common.paging.Page;
import com.party.common.utils.BigDecimalUtils;
import com.party.common.utils.LangUtils;
import com.party.common.utils.PartyCode;
import com.party.common.utils.StringUtils;
import com.party.core.model.YesNoStatus;
import com.party.core.model.member.MemberBank;
import com.party.core.model.member.MemberCopartnerCount;
import com.party.core.model.member.MemberGroup;
import com.party.core.model.system.SysConfig;
import com.party.core.model.wallet.Withdrawals;
import com.party.core.service.copartner.IBrokerageItemService;
import com.party.core.service.mall.IMallOrderDetailService;
import com.party.core.service.member.IMemberBankService;
import com.party.core.service.member.IMemberCopartnerCountService;
import com.party.core.service.member.IMemberGroupService;
import com.party.core.service.system.ISysConfigService;
import com.party.core.service.wallet.IWithdrawalService;
import com.party.core.service.wallet.biz.WithdrawalsBizService;
import com.party.core.utils.MyBeanUtils;
import com.party.mobile.biz.copartner.BrokerageBizService;
import com.party.mobile.biz.currentUser.CurrentUserBizService;
import com.party.mobile.web.dto.AjaxResult;
import com.party.mobile.web.dto.login.output.CurrentUser;
import com.party.mobile.web.dto.member.output.WithdrawalOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.List;

/**
 * @Author: Administrator.
 * @Description: 提现控制器
 * @Date:Created in 2017/10/26 0026 上午 9:32.
 */
@Controller
@Authorization
@RequestMapping("system/withdrawal")
public class WithdrawalController {
    @Autowired
    private CurrentUserBizService currentUserBizService;
    @Autowired
    private IMemberBankService memberBankService;
    @Autowired
    private IBrokerageItemService brokerageItemService;
    @Autowired
    private WithdrawalsBizService withdrawalsBizService;
    @Autowired
    private IWithdrawalService withdrawalService;
    @Autowired
    private ISysConfigService sysConfigService;
    @Autowired
    private IMallOrderDetailService mallOrderDetailService;
    @Autowired
    private BrokerageBizService brokerageBizService;
    @Autowired
    private IMemberCopartnerCountService memberCopartnerCountService;

    @Autowired
    private IMemberGroupService memberGroupService;

    Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 绑定银行卡
     *
     * @param memberBank
     * @param result
     * @return
     */
    @ResponseBody
    @RequestMapping("bindBankCard")
    public AjaxResult bindBankCard(MemberBank memberBank, BindingResult result, HttpServletRequest request) {
        if (result.hasErrors()) {
            List<ObjectError> allErrors = result.getAllErrors();
            String description = allErrors.get(0).getDefaultMessage();
            return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, description);
        }

        try {
            CurrentUser currentUser = currentUserBizService.getCurrentUser(request);
            String memberId = currentUser.getId();
            if (null != currentUser.getIsMemberGroup() && YesNoStatus.YES.getCode().equals(currentUser.getIsMemberGroup())) {
                memberId = memberGroupService.getPartnerId(currentUser.getId());
            }
            MemberBank dbBank = memberBankService.findByMemberId(memberId);
            if (dbBank == null) {
                dbBank = new MemberBank();
                dbBank.setCreateBy(currentUser.getId());
                dbBank.setUpdateBy(currentUser.getId());
                dbBank.setMemberId(currentUser.getId());
            }
            MyBeanUtils.copyBeanNotNull2Bean(memberBank, dbBank);
            if (StringUtils.isEmpty(dbBank.getId())) {
                memberBankService.insert(dbBank);
            } else {
                memberBankService.update(dbBank);
            }
        } catch (Exception e) {
            logger.error("绑定银行卡异常", e);
            return AjaxResult.error(101, "绑定银行卡异常");
        }
        return AjaxResult.success();
    }

    /**
     * 银行卡信息/可提现金额
     *
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping("memberBankInfo")
    public AjaxResult memberBankInfo(HttpServletRequest request) {
        try {
            CurrentUser currentUser = currentUserBizService.getCurrentUser(request);
            String memberId = currentUser.getId();
            if (null != currentUser.getIsMemberGroup() && YesNoStatus.YES.getCode().equals(currentUser.getIsMemberGroup())) {
                memberId = memberGroupService.getPartnerId(currentUser.getId());
            }
            MemberBank memberBank = memberBankService.findByMemberId(memberId); // 银行卡信息
            return AjaxResult.success(memberBank);
        } catch (Exception e) {
            logger.error("获取银行卡信息异常", e);
            return AjaxResult.error(100, "获取银行卡信息异常");
        }
    }

    /**
     * 获取可提现金额
     *
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping("getWithdrawTotal")
    public AjaxResult getWithdrawTotal(HttpServletRequest request, Integer type) {
        try {
            if (type == null) {
                type = Withdrawals.TYPE_BROKERAGE;
            }
            CurrentUser currentUser = currentUserBizService.getCurrentUser(request);

//            MemberCopartnerCount query = new MemberCopartnerCount();
//            query.setMemberId(currentUser.getId());
//            MemberCopartnerCount sum = memberCopartnerCountService.sum(query);

            // 可提现佣金
            Double brokerageTotal = brokerageBizService.getCanBrokerage(type, currentUser.getId());
//            // 累计提现
            Double withdrawalTotal = withdrawalsBizService.getWithdrawalTotal(currentUser.getId(), type,null);
            double subTotal = BigDecimalUtils.sub(brokerageTotal, withdrawalTotal);
            subTotal = BigDecimalUtils.round(subTotal, 2);
            return AjaxResult.success(subTotal);
        } catch (Exception e) {
            logger.error("获取可提现金额异常", e);
            return AjaxResult.error(101, "获取可提现金额异常");
        }
    }

    /**
     * 申请提现
     *
     * @param memberBankId 用户绑定银行卡id
     * @param payment      提现金额
     * @param type         提现类型 2（佣金），3（商城分销）
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "applyWithdrawal", method = RequestMethod.POST)
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public AjaxResult applyWithdrawal(String memberBankId, Float payment, Integer type, HttpServletRequest request) {
        try {
            if (null == type) {
                type = Withdrawals.TYPE_BROKERAGE;
            }
            if (StringUtils.isEmpty(memberBankId)) {
                return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "银行卡id不能为空");
            }
            if (null == type) {
                return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "提现类型不能为空");
            }
            if (null == payment || payment == 0f) {
                return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "提现金额无效");
            }
            if (Withdrawals.TYPE_MALL.equals(type)) {
                SysConfig mallMin = sysConfigService.findByCode("mallMin");
                SysConfig mallMax = sysConfigService.findByCode("mallMax");
                Float min = 0f;
                Float max = 0f;
                if (null != mallMin && StringUtils.isNotEmpty(mallMin.getValue())) {
                    min = Float.valueOf(mallMin.getValue());
                }
                if (null != mallMax && StringUtils.isNotEmpty(mallMax.getValue())) {
                    max = Float.valueOf(mallMax.getValue());
                }

                if (!(new Float(0).equals(min) || new Float(0).equals(max))) {
                    if (payment < min || payment > max) {
                        DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
                        df.applyPattern("#.##");
                        return AjaxResult.error(100, "提现金额不能低于" + df.format(min) + "；不能高于" + df.format(max));
                    }
                }
            }

            MemberBank memberBank = memberBankService.get(memberBankId);
            if (memberBank == null) {
                return AjaxResult.error(PartyCode.IS_NO_DATA, "银行卡不存在");
            }

            CurrentUser currentUser = currentUserBizService.getCurrentUser(request);

            synchronized (this) {
                // 可提现佣金
                Double brokerageTotal = brokerageBizService.getCanBrokerage(type, currentUser.getId());
                // 累计提现
                Double withdrawalTotal = withdrawalsBizService.getWithdrawalTotal(currentUser.getId(), type,null);

                double subTotal = BigDecimalUtils.sub(brokerageTotal, withdrawalTotal);
                subTotal = BigDecimalUtils.round(subTotal, 2);

                if (new BigDecimal(payment.toString()).compareTo(new BigDecimal(Double.toString(subTotal))) > 0) {
                    return AjaxResult.error(120, "提现金额不能高于可提现金额");
                }
                withdrawalsBizService.insertWithdrawal(memberBank, currentUser.getId(), type, payment,null,0d,0d);
            }
            return AjaxResult.success();
        } catch (Exception e) {
            logger.error("申请提现异常", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(110, "申请提现异常");
        }
    }

    /**
     * 提现详情
     *
     * @param id 提现id
     * @return
     */
    @ResponseBody
    @RequestMapping("withdrawalDetail")
    public AjaxResult withdrawalDetail(String id) {
        if (StringUtils.isNotEmpty(id)) {
            Withdrawals withdrawal = withdrawalService.get(id);
            // 手续费
            double serviceFee = BigDecimalUtils.mul(withdrawal.getPayment(), Withdrawals.SERVER_FEE);
            serviceFee = BigDecimalUtils.round(serviceFee, 2);
            withdrawal.setServiceFee(serviceFee);
            return AjaxResult.success(withdrawal);
        }
        return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "id不能为空");
    }

    /**
     * 提现流水
     *
     * @param request 当前用户
     * @param type    类型 1：余额 2：佣金 3：商城分销
     * @param page    分页
     * @return
     */
    @ResponseBody
    @RequestMapping("withdrawalList")
    public AjaxResult withdrawalList(HttpServletRequest request, Integer type, Page page) {
        try {
            CurrentUser currentUser = currentUserBizService.getCurrentUser(request);

            String memberId = currentUser.getId();
            if (new Integer(3).equals(type)) {
                memberId = memberGroupService.getPartnerId(currentUser.getId());
            }

            Withdrawals withdrawal = new Withdrawals();
            withdrawal.setCreateBy(memberId);
            withdrawal.setType(type);
            List<Withdrawals> withdrawals = withdrawalService.listPage(withdrawal, page);
            List<WithdrawalOutput> outputs = LangUtils.transform(withdrawals, new Function<Withdrawals, WithdrawalOutput>() {
                @Nullable
                @Override
                public WithdrawalOutput apply(@Nullable Withdrawals input) {
                    WithdrawalOutput output = new WithdrawalOutput();
                    output.setId(input.getId());
                    output.setCreateDate(input.getCreateDate());
                    output.setStatus(input.getStatus());
                    output.setPayment(input.getPayment());
                    return output;
                }
            });
            return AjaxResult.success(outputs, page);
        } catch (Exception e) {
            logger.error(type + "提现列表异常", e);
            return AjaxResult.error(100, "提现列表异常");
        }
    }
}
